﻿using System;
using System.IO;

using Microsoft.Xna.Framework;

using xEngine.Utils;

namespace xEngine.Debugging
{
    public class LogWriter
    {
        #region Singleton

        private static LogWriter inst = new LogWriter();
        private LogWriter()
        {
            LogDirectory = "logs";
            LogPrefix = "";
            LogPostfix = "";
            LogExtension = "txt";
            TimeStamp = true;
        }

        #endregion

        #region Member Variables
        #endregion

        #region Properties

        public static string LogPath
        {
            get
            {
                string fn = LogDirectory + "/" + LogPrefix + Date + LogPostfix + "." + LogExtension;

                if (!Directory.Exists(LogDirectory))
                    Directory.CreateDirectory(LogDirectory);

                if (!File.Exists(fn))
                {
                    FileStream fs = File.Create(fn);
                    fs.Close();
                }

                return fn;
            }
        }
        public static string LogDirectory { get; set; }
        public static string LogPrefix { get; set; }
        public static string LogPostfix { get; set; }
        public static string LogExtension { get; set; }
        public static bool TimeStamp { get; set; }

        private static string Date
        {
            get
            {
                DateTime now = DateTime.Now;
                return now.Year + "-" + AppendLeadingZero(now.Month) + "-" + AppendLeadingZero(now.Day);
            }
        }
        private static string Time
        {
            get
            {
                DateTime now = DateTime.Now;
                return AppendLeadingZero(now.Hour) + ":" + AppendLeadingZero(now.Minute) + ":" + AppendLeadingZero(now.Second) + "." + AppendLeadingZero(now.Millisecond, 3);
            }
        }

        public static object WriteLine
        {
            set
            {
                string c;
                LogLevel l = LogLevel.Info;

                if (value == null)
                {
                    c = "NULL";
                    l = LogLevel.Warning;
                }
                else
                {
                    if (value.GetType().BaseType.Name.Contains("Exception"))
                    {
                        c = ((Exception)value).Message + "\r\n" + ((Exception)value).StackTrace;
                        l = LogLevel.Error;
                    }
                    else if (value.GetType().Name == "CompilerError")
                    {
                        System.CodeDom.Compiler.CompilerError ce = (System.CodeDom.Compiler.CompilerError)value;
                        c = "Compiler Error @ Line " + ce.Line + ": " + ce.ErrorText;
                        l = LogLevel.Error;
                    }
                    else
                    {
                        c = value.ToString();
                    }
                }

                if (OnWriteLine != null)
                    OnWriteLine(inst, new LogEventArgs(c, l));

                File.AppendAllText(LogPath, (TimeStamp ? "[" + Time + "]" : "") + c + "\r\n");
            }
        }

        #endregion

        #region Functions

        private static string AppendLeadingZero(int value)
        {
            return AppendLeadingZero(value, 2);
        }
        private static string AppendLeadingZero(int value, int digits)
        {
            string val = "" + value;

            while (val.Length < digits)
                val = "0" + val;

            return val;
        }

        #endregion

        #region Events

        public static event EventHandler<LogEventArgs> OnWriteLine;

        #endregion

    }

    public enum LogLevel
    {
        Info,
        Warning,
        Error
    }

    public class LogEventArgs : EventArgs
    {
        public string Message;
        public LogLevel LogLevel;

        public LogEventArgs(string m, LogLevel l)
        {
            Message = m;
            LogLevel = l;
        }
    }
}
